/* Copyright (c) 2006, Jan Flora <janflora@diku.dk>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the University of Copenhagen nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
  @author Jan Flora <janflora@diku.dk>
*/

#ifndef _FRAME_H_
#define _FRAME_H_

// These small cryptic macros produces the number of
// addressing bits, given an addressing mode.
// We exploit, that 3 is the only odd mode. And that
// the other modes are equal to their address lengths.

#define mhrDstPANLength(mode)                (mode?2:0)
#define mhrSrcPANLength(mode, intraPAN)      ((!intraPAN&&mode)?2:0)
#define mhrAddrLength(mode)                  (((mode)&1)?8:(mode))
#define mhrDstAddrModeLength(mode)           mhrDstPANLength(mode) + mhrAddrLength(mode)
#define mhrSrcAddrModeLength(mode, intraPAN) mhrSrcPANLength(mode, intraPAN) + mhrAddrLength(mode)

typedef struct
{
	uint8_t FrameType       : 3;
	uint8_t SecurityEnabled : 1;
	uint8_t FramePending    : 1;
	uint8_t AckRequest      : 1;
	uint8_t IntraPAN        : 1;
	uint8_t Reserved1_2     : 1;
	
	uint8_t Reserved1_1     : 2;
	uint8_t DstAddrMode     : 2;
	uint8_t Reserved2       : 2;
	uint8_t SrcAddrMode     : 2;
} frameControl_t;

// The static part of the MHR represented as a struct.
// This is useful when addressing information is not needed.
typedef struct
{
	frameControl_t frameControl;
	uint8_t        seqNum;
} macMhrStatic_t;

// All MHR information represented as a structure.
// Since the MHR has variable length, the 802.15.4 frames
// are not castable as macMhr_t's.
typedef struct
{
	frameControl_t *frameControl;
	uint8_t *seqNum;
	uint8_t *dstPan;
	uint8_t *dstAddr;
	uint8_t *srcPan;
	uint8_t *srcAddr;
	uint8_t *payload;
} macMhr_t;


// Beacon frame MSDU.

typedef struct
{
	uint8_t BeaconOrder          :4;
	uint8_t SuperframeOrder      :4;
	
	uint8_t FinalCAPSlot         :4;
	uint8_t BatteryLifeExtension :1;
	uint8_t Reserved             :1;
	uint8_t PANCoordinator       :1;
	uint8_t AssociationPermit    :1;

} msduSuperframeSpec_t;

typedef struct
{
	uint8_t GTSDescriptorCount :3;
	uint8_t Reserved           :4;
	uint8_t GTSPermit          :1;
} msduGTSSpec_t;

typedef struct
{
	uint8_t GTSDirectionMask :7;
	uint8_t Reserved         :1;
} msduGTSDirections_t;

typedef struct
{
	uint16_t DeviceShortAddress :16;
	uint8_t GTSStartingSlot     :4;
	uint8_t GTSLength           :4;
} msduGTSList_t;

typedef struct
{
	uint8_t NumShortAddrsPending :3;
	uint8_t Reserved1            :1;
	uint8_t NumExtAddrsPending   :3;
	uint8_t Reserved2            :1;
} msduPendingAddrSpec_t;

typedef struct
{
	msduSuperframeSpec_t  *sfSpec;
	msduGTSSpec_t         *gtsSpec;
	msduGTSDirections_t   *gtsDirs;
	msduGTSList_t         *gtsList;
	msduPendingAddrSpec_t *addrSpec;
	uint8_t               *addrList;
	uint8_t               *payload;
} macBeaconPayload_t;


// Command frame MSDU's

typedef struct
{
	uint8_t commandFrameIdent;
} macCommandPayload_t;

typedef struct
{
	uint8_t  commandFrameIdent;
	uint16_t shortAddr;
	uint8_t  status;
} macAssocResponse_t;

typedef struct
{
	uint8_t AltPANCoordinator  :1;
	uint8_t DeviceType         :1;
	uint8_t PowerSource        :1;
	uint8_t RecvOnWhenIdle     :1;
	uint8_t Reserved           :2;
	uint8_t SecurityCapability :1;
	uint8_t AllocateAddress    :1;
} msduAssocCapabilityInfo_t;

typedef struct
{
	uint8_t                   commandFrameIdent;
	msduAssocCapabilityInfo_t capabilityInfo;
} macAssocRequest_t;

typedef struct
{
	uint8_t commandFrameIdent;
	uint8_t reason;
} macDisassocNotification_t;

typedef struct
{
	uint8_t  commandFrameIdent;
	uint16_t coordPanId;
	uint16_t coordShortAddr;
	uint8_t  channel;
	uint16_t assignedShortAddr;
} macCoordRealignment_t;

typedef struct
{
	uint8_t GTSLength      :4;
	uint8_t GTSDirection   :1;
	uint8_t CharType       :1;
	uint8_t Reserved       :2;
} msduGtsCharacteristics_t;

typedef struct
{
	uint8_t commandFrameIdent;
	msduGtsCharacteristics_t gtsChars;
} macGtsRequest_t;

#endif
